<!DOCTYPE html>
<html lang="ko">

<head>
	<meta charset="utf-8">
	<base href="../../../" />
	<script src="page.js"></script>
	<link type="text/css" rel="stylesheet" href="page.css" />
</head>

<body>
	<h1>오브젝트를 폐기하는 방법([name])</h1>

	<p>
        애플리케이션에서 성능을 개선하고 메모리 누수를 방지하기 위한 중요한 한 가지는 사용되지 않는 라이브러리 개체를 폐기하는 것입니다.
        *three.js* 유형의 인스턴스는 생성될 때마다 일정량의 메모리를 할당하게 됩니다. 하지만 *three.js*는 특정 개체에 대해 기하학적 구조나 WebGL 관련 재질(예: 버퍼 또는 쉐이더 프로그램) 개체의 렌더링에 필요한 것입니다. 
        이러한 오브젝트들은 자동으로 폐기되지 않는다는 점을 주의하세요. 대신, 애플리케이션에서는 메모리 자원을 확보하기 위해 특별한 API를 사용해야 합니다.
        이 가이드에서는 이 API의 사용 방법과 이와 관련해서 어떤 오브젝트가 있는지에 대한 간략한 설명을 제공해 드립니다.
	</p>

	<h2>기하학</h2>

	<p>
        기하학은 속성 집합으로 정의된 꼭짓점 정보를 표시하는데, *three.js*는 속성마다 하나의 [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer] 유형의 대상을 만들어 내부에 저장합니다.
        이러한 개체는 [page:BufferGeometry.dispose]를 호출할 때만 폐기됩니다.
        만약 애플리케이션에서 기하학을 더이상 사용하지 않는다면, 이 방법을 실행하여 모든 관련 자원을 폐기하세요.
	</p>

	<h2>재질</h2>

	<p>
        재질은 오브젝트가 어떻게 렌더링되는지를 정의합니다. *three.js*는 재질에 정의된 정보를 사용하여 렌더링을 위한 하나의 셰이더 프로그램을 구축합니다.
        셰이더 프로그램은 해당 재질이 폐기된 후에만 삭제할 수 있습니다. 성능상의 이유로 *three.js*는 가능하다면 활용 가능한 셰이더 프로그램을 재사용하게 되어 있습니다. 따라서 셰이더 프로그램은 모든 관련된 재질들이 사라진 후에야 삭제됩니다.
        [page:Material.dispose]() 를 실행함으로써 재질을 폐기할 수 있습니다.
	</p>

	<h2>텍스쳐</h2>

	<p>
        재질의 폐기는 텍스쳐에 영향을 미치지 않습니다. 이들은 분리되어 있어 하나의 텍스쳐를 여러 재질로 동시에 사용할 수 있습니다.
        [page:Texture] 인스턴스를 만들 때마다 three.js는 내부에서 [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture] 인스턴스를 만듭니다.
        buffer와 비슷하게, 이 오브젝트는 [page:Texture.dispose]() 호출로만 삭제가 가능합니다.
	</p>

	<h2>렌더링 대상</h2>

	<p>
        [page:WebGLRenderTarget] 타입의 오브젝트는 [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture]의 인스턴스가 할당되어 있을 뿐만 아니라,
        [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer WebGLFramebuffer]와 [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer WebGLRenderbuffer] 도 할당되어, 
        커스텀 렌더링 목표를 실체화합니다. 이러한 오브젝트는 [page:WebGLRenderTarget.dispose]()를 실행해야만 폐기할 수 있습니다.
	</p>

	<h2>그밖의 것들</h2>

	<p>
        컨트롤러나 후기 처리 프로세스처럼 *dispose()* 메서드가 제공되어 내부 이벤트리스너나 렌더링 대상을 폐기하는 examples 폴더에서 가져온 것들이 있습니다.
        일반적으로 API나 파일을 열람하고 *dispose()* 를 확인하는 것이 좋습니다. 만약 이 메서드가 존재한다면 당연히 그 메서드를 폐기 시에 사용해야 합니다.e it when cleaning things up.
	</p>

	<h2>FAQ</h2>

	<h3>*three.js*는 왜 자동으로 오브젝트를 폐기 못하나요?</h3>

	<p>
        이 문제가 커뮤니티에서 여러 차례 제기돼 온 만큼 확실한 대답을 해 드려야겠습니다. 사실, *three.js*는 사용자가 만든 개체(예를 들어 기하체 또는 재질)의 라이프사이클이나 역할 범위를 알지 못하며, 이는 애플리케이션의 책임입니다.
        예를 들어, 만약 하나의 재질이 현재 렌더링에 사용되고 있지 않더라도, 바로 다음 프레임에 필수적인 재질일 수 있을 것입니다. 그래서 만약 애플리케이션에서 특정 오브젝트가 삭제되어도 된다고 하면,
        해당하는 *dispose()* 메서드를 통해 엔진에 알려줘야 합니다.
	</p>

	<h3>화면에서 mesh를 지우는 것도 geometry와 material을 폐기시키나요?</h3>

	<p>
		아니요, *dispose()*를 통해 명시적으로 geometry와 material을 폐기해야합니다. geometry와 material은 mesh와 마찬가지로 3D 오브젝트에서 활용할 수 있다는 점을 명심하세요.
	</p>

	<h3>*three.js*에서 캐시화된 오브젝트의 수를 알 수 있나요?</h3>

	<p>
        네, 렌더러의 그래빅 보드와 렌더링 프로세스의 통계 정보를 담고 있는 특수 속성인 [page: WebGLRenderer.info]를 통해 확인할 수 있습니다. 
        다른 것 보다도, 이를 통해 내부적으로 많은 텍스쳐와 기하학, 셰이더 프로그램이 저장되어 있다는 것을 알 수 있습니다.
        만약 애플리케이션에서 성능 문제를 발견했다면, 바로 이 속성을 조절하여 쉽게 메모리 누출을 확인할 수 있습니다.
	</p>

	<h3>이미지가 아직 로딩이 안 됐는데 텍스쳐에서 *dispose()*를 해버리면 어떻게 되나요?</h3>

	<p>
		텍스쳐와 관련된 내부 자원은 이미지가 완전히 로딩됐을때밖에 할당이 되지 않습니다. 만약 이미지 로딩 전에 텍스쳐를 폐기해버렸다면,
		아무 일도 일어나지 않을 것입니다. 아무런 자원도 할당되지 않았고 지울 것도 없기 때문입니다.
	</p>

	<h3>*dispose()*를 하고 나서 나중에 다시 각각의 오브젝트를 사용하면 어떻게 되나요?</h3>

	<p>
        삭제된 내부 자원이 엔진에서 다시 생성될 것입니다. 런타임 에러는 발생하지 않겠지만 프레임에 부정적인 영향을 미치는 것을 확인할 수 있을 것이고 
        특히 셰이더 프로그램을 컴파일할 때 더 두드러질 것입니다.
	</p>

	<h3>*three.js* 오브젝트를 앱에서 어떻게 관리해야 할까요? 언제 폐기해야되는지 어떻게 알죠?</h3>

	<p>
        일반적으로 이 점에 대한 명확한 해답은 없습니다. *dispose()*는 구체적인 사용 방법에 따라 적절히 활용하는 방법이 좌우됩니다. 굳이 오브젝트를 자꾸 폐기할 필요는 없다는 것을 기억해 두세요.
        다양한 레벨로 구성된 게임이 좋은 예가 될 수 있을 것입니다. 레벨이 바뀌면, 폐기를 할 때입니다. 애플리케이션은 오래된 화면을 지나가면서 오래된 재질, 기하학, 텍스쳐를 모두 폐기할 수 있습니다.
        앞의 장에서 언급한 바와 같이 만약 여전히 사용하고 있는 오브젝트를 폐기해도 런타임 에러를 만들지는 않을 것입니다. 단일 프레임에서 퍼포먼스가 떨어지는 정도가 가장 안 좋은 정도일 것입니다.
	</p>

	<h2>dispose() 사용법 예제</h2>

	<p>
		[example:webgl_test_memory WebGL / test / memory]<br />
		[example:webgl_test_memory2 WebGL / test / memory2]<br />
	</p>

</body>

</html>